package back_end;

import java.sql.*;
import java.util.ArrayList;
import java.util.Collections;

abstract class Operator {
    protected String name;
    protected ArrayList<String> needs;
    protected ArrayList<String> p;
    protected int level;
    abstract String perform();
    void init(String prmts) {
    	p.clear();
        Collections.addAll(p, prmts.split(" "));
    }
    protected int getLevel() {
    	return level;
    }
    boolean checkISBN(long i) throws SQLException {
        //瀹為檯鎯呭喌涓璉SBN鏈夐暱搴﹁寖鍥村拰鏍￠獙瑙勫垯锛屾椤圭洰涓拷鐣�
        Connection conn = MysqlConnection.getConn();
        Statement stmt = conn.createStatement();
        ResultSet r = stmt.executeQuery("select ISBN from books where ISBN=" + i + ";");
        return r.next();
    }
    boolean checkNumber(long n) throws SQLException {
        //瀹為檯鎯呭喌涓畞澶忓ぇ瀛﹀鍙锋湁鍥哄畾鐨勯暱搴﹀拰鏋勬垚鏂瑰紡锛屾椤圭洰涓拷鐣�
        Connection conn = MysqlConnection.getConn();
        Statement stmt = conn.createStatement();
        ResultSet r = stmt.executeQuery("select number from students where number=" + n + ";");
        return r.next();
    }
    int checkUser(long num) throws SQLException {
        if (!MysqlConnection.getStatus() || !checkNumber(num)) {
            return -1;
        }
        Connection conn = MysqlConnection.getConn();
        PreparedStatement pstmt = conn.prepareStatement("select * from students where number=?");
        pstmt.setLong(1, num);
        ResultSet result = pstmt.executeQuery();
        boolean out = false;
        if (result.next()) {
            if (result.getInt("count") >= 5 || result.getInt("permission") < 1) {
                return -1;
            }
            int cnt = result.getInt("count");
            for (int i = 1; i <= cnt; i++) {
                //Date date = new Date();
                java.sql.Date date = new java.sql.Date(System.currentTimeMillis());
                if (date.after(result.getDate("dueCutoff" + i))) {
                    out = true;
                    break;
                }
            }
            if (out) {
                Statement stmt = conn.createStatement();
                stmt.execute("update students set permission=0 where number=" + num + ";");
                return -1;
            } else {
                return cnt;
            }
        }
        return -1;
    }
}
class Borrow extends Operator {
    Borrow() {
        name = "borrow";
        needs = new ArrayList<>();
        needs.add("number");
        needs.add("ISBN");
        p = new ArrayList<>();
        level = 1;
    }
    String perform() {
        int cnt = -1;
        long stuNum = Long.parseLong(p.get(0));
        long isbn = Long.parseLong(p.get(1));
        try {
            if (p.size() < 2 || !checkISBN(isbn) || !checkNumber(stuNum)) {
                return "Fail: illegal parameters.";
            }
            cnt = checkUser(stuNum);
            if (cnt == -1) {
                return "Fail: less privileged user";
            }
            if (!MysqlConnection.getStatus()) {
                return "Fail: database disconnected.";
            }
        } catch (NumberFormatException e) {
            e.printStackTrace();
            return "Fail: illegal parameters.";
        } catch (SQLException e) {
            e.printStackTrace();
            return "Fail: database disconnected.";
        }
        cnt++;
        Connection conn = MysqlConnection.getConn();
        try {
            Statement stmt = conn.createStatement();
            ResultSet r = stmt.executeQuery("select * from books where ISBN=" + p.get(1) + ";");
            if (r.next() && r.getInt("available") > 0) {
                PreparedStatement pstmt = conn.prepareStatement("update students set ISBN" + cnt + "=?, dueCutOff" + cnt + "=?, count=count+1 where number=?;");
                pstmt.setLong(1, isbn);
                java.sql.Date date = new java.sql.Date(System.currentTimeMillis() + 30L * 24 * 60 * 60 * 1000);
                pstmt.setDate(2, date);
                pstmt.setLong(3, stuNum);
                int rst = pstmt.executeUpdate();
                stmt.executeUpdate("update books set available=available-1 where ISBN=" + p.get(1) + ";");
            } else {
                return "Fail: not available.";
            }

        } catch (SQLException e) {
            e.printStackTrace();
            return "Fail: database server exception.";
        }
        return "Success.";
    }
}
class reeturn extends Operator {
    reeturn() {
        name = "return";
        needs = new ArrayList<>();
        needs.add("number");
        needs.add("ISBN");
        p = new ArrayList<>();
        level = 0;
    }
    String perform() {
        long stuNum = Long.parseLong(p.get(0));
        long isbn = Long.parseLong(p.get(1));
        try {
            if (p.size() < 2 || !checkISBN(isbn) || !checkNumber(stuNum)) {
                return "Fail: illegal parameters.";
            }
        } catch (NumberFormatException e) {
            e.printStackTrace();
            return "Fail: illegal parameters.";
        } catch (SQLException e) {
            e.printStackTrace();
            return "Fail: database disconnected.";
        }
        Connection conn = MysqlConnection.getConn();
        try {
            PreparedStatement pstmt = conn.prepareStatement("select * from students where number=?");
            pstmt.setLong(1, stuNum);
            ResultSet rs = pstmt.executeQuery();
            if (rs.next()) {
                for (int i = 1; i <= 5; i++) {
                    if (rs.getLong("ISBN" + i) == isbn) {
                        Statement stmt = conn.createStatement();
                        stmt.execute("update books set available=available+1 where ISBN=" + p.get(1) + ";");
                        PreparedStatement p2 = conn.prepareStatement("update students set ISBN" + i + "=?, dueCutOff" + i + "=?, count=count-1 where number=?;");
                        p2.setLong(3, stuNum);
                        if (rs.getInt("count") != i) {
                            int j = rs.getInt("count");
                            p2.setLong(1, rs.getLong("ISBN" + j));
                            p2.setDate(2, rs.getDate("dueCutOff" + j));
                            p2.executeUpdate();
                            PreparedStatement p3 = conn.prepareStatement("update students set ISBN" + j + "=?, dueCutOff" + j + "=? where number=?;");
                            p3.setString(1, "null");
                            p3.setString(2, "null");
                            p3.setLong(3, stuNum);
                            p3.executeUpdate();
                        } else {
                            p2.setNull(1, Types.BIGINT);
                            p2.setNull(2, Types.BIGINT);
                            p2.executeUpdate();
                        }
                        return "Success.";
                    }
                    if (i == 5) {
                        return "Fail: ISBN not found in this account.";
                    }
                }
            }
        } catch (SQLException e) {
            e.printStackTrace();
            return "Fail: database server exception.";
        }
        return "Fail: unknown";
    }
}
class search extends Operator {
    search() {
        name = "search";
        needs = new ArrayList<>();
        needs.add("keyword");
        p = new ArrayList<>();
        level = 0;
    }
    String perform() {
        Connection conn = MysqlConnection.getConn();
        if (p.size() < 1) {
            return "Fail: illegal parameters.";
        }
        try {
            PreparedStatement preparedStatement = conn.prepareStatement("select * from books where title like ? || author like ?;");
            preparedStatement.setString(1, "%" + p.get(0) + "%");
            preparedStatement.setString(2, "%" + p.get(0) + "%");
            ResultSet rs = preparedStatement.executeQuery();
            StringBuilder ret = new StringBuilder();
            while (rs.next()) {
                ret.append(rs.getString("title")).append(" ");
                ret.append(rs.getString("author")).append(" ");
                ret.append(rs.getString("ISBN")).append(" ");
                ret.append(rs.getString("available")).append(" ");
            }
            return "Success " + ret;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "Fail.";
    }
}
class showBorrowed extends Operator {
    showBorrowed() {
        name = "showBorrowed";
        needs = new ArrayList<>();
        needs.add("number");
        p = new ArrayList<>();
        level = 0;
    }
    String perform() {
        Connection conn = MysqlConnection.getConn();
        long stuNum = Long.parseLong(p.get(0));
        try {
            if (p.size() < 1 || !checkNumber(stuNum)) {
                return "Fail: illegal parameters.";
            }
        } catch (SQLException e) {
            e.printStackTrace();
            return "Fail: database disconnected.";
        }
        try {
            PreparedStatement pstmt = conn.prepareStatement("select * from students where number=?");
            pstmt.setLong(1, stuNum);
            ResultSet rs = pstmt.executeQuery();
            if (rs.next()) {
                StringBuilder ret = new StringBuilder();
                for (int i = 1; i <= rs.getInt("count"); i++) {
                    Statement stmt = conn.createStatement();
                    ResultSet rst = stmt.executeQuery("select * from books where ISBN=" + rs.getLong("ISBN" + i) + ";");
                    if (rst.next()) {
                        ret.append(rst.getString("title")).append(" ");
                        ret.append(rst.getString("author")).append(" ");
                        ret.append(rs.getString("dueCutOff" + i)).append(" ");
                        ret.append(rs.getString("ISBN" + i)).append(" ");
                    }
                }
                return "Success " + ret;
            }
        } catch (SQLException e) {
            e.printStackTrace();
            return "Fail: database server exception.";
        }
        return "Fail.";
    }
}
class check extends Operator {
    check() {
        name = "check";
        needs = new ArrayList<>();
        level = 1;
        needs.add("number");
        p = new ArrayList<>();
    }
    String perform() {
        Connection conn = MysqlConnection.getConn();
        long stuNum = Long.parseLong(p.get(0));
        try {
            if (p.size() < 1 || !checkNumber(stuNum)) {
                return "Fail: illegal parameters.";
            }
        } catch (SQLException e) {
            e.printStackTrace();
            return "Fail: database disconnected.";
        }
        try {
            int c = checkUser(stuNum);
            if (c == -1) {
                return "0";
            } else {
                Statement stmt = conn.createStatement();
                ResultSet rs = stmt.executeQuery("select permission from students where number=" + stuNum + ";");
                if (rs.next())
                    return "Success " + rs.getInt(1);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return "Fail.";
    }
}
class recommend extends Operator {
    recommend() {
        name = "recommend";
        needs = new ArrayList<>();
        needs.add("title");
        needs.add("author");
        needs.add("ISBN");
        level = 2;
        p = new ArrayList<>();
    }
    String perform() {
        Connection conn = MysqlConnection.getConn();
        try {
            long isbn = Long.parseLong(p.get(2));
            if (p.size() < 3 || !checkISBN(isbn)) {
                return "Fail: illegal parameters.";
            }
            Statement stmt = conn.createStatement();
            ResultSet rs = stmt.executeQuery("select ISBN from recommenditions where ISBN=" + p.get(2) + ";");
            if (rs.next()) {
                stmt.executeUpdate("update recommenditions set count=count+1 where ISBN=" + p.get(2) + ";");
            } else {
                stmt.executeUpdate("insert into recommenditions values(" + p.get(2) + ", " + p.get(0) + ", " + p.get(1) + ", 0;");
            }
            return "Success.";
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return "Fail";
    }
}

class freezing extends Operator {
	freezing() {
        name = "freezing";
        needs = new ArrayList<>();
        needs.add("number");
        level = 2;
        p = new ArrayList<>();
    }
	@Override
	String perform() {
		Long number = Long.parseLong(p.get(0));
		try {
			if (p.size() < 1 || !checkNumber(number)) {
				return "Fail: illegal parameters.";
			}
		} catch (SQLException e1) {
			// TODO 自动生成的 catch 块
			e1.printStackTrace();
		}
		Connection con = MysqlConnection.getConn();
		try {
			PreparedStatement pps = con.prepareStatement("update students set permission = 1 where number = ?");
			pps.setLong(1, number);
			pps.executeUpdate();
			return "Success";
		} catch (SQLException e) {
			// TODO 自动生成的 catch 块
			e.printStackTrace();
		}
		return "False";
	}
	
}

class showStudents extends Operator {
	showStudents() {
        name = "freezing";
        needs = new ArrayList<>();
        level = 2;
        p = new ArrayList<>();
    }
	@Override
	String perform() {
		// TODO 自动生成的方法存根
		Connection con = MysqlConnection.getConn();
		try {
			Statement stmt = con.createStatement();
			String sql = "select * from students where permission = 0";
			ResultSet rs = stmt.executeQuery(sql);
			StringBuilder ret = new StringBuilder();
			while (rs.next()) {
				ret.append(rs.getString("name")).append(" ");
				ret.append(rs.getString("permission")).append(" ");
				ret.append(rs.getString("number")).append(" ");
			}
			return "Success " +ret;
		} catch (SQLException e) {
			// TODO 自动生成的 catch 块
			e.printStackTrace();
		}
		return "False";
	}
	
}

class showRecoms extends Operator {
	showRecoms() {
		name = "showRecoms";
        needs = new ArrayList<>();
        level = 2;
        p = new ArrayList<>();
	}
	@Override
	String perform() {
		// TODO 自动生成的方法存根
		Connection con = MysqlConnection.getConn();
		try {
			Statement stmt = con.createStatement();
			String sql = "select * from recommendations";
			ResultSet rs = stmt.executeQuery(sql);
			StringBuilder rst = new StringBuilder();
			while (rs.next()) {
				rst.append(rs.getString("title")).append(" ");
				rst.append(rs.getString("author")).append(" ");
				rst.append(rs.getString("ISBN")).append(" ");
				rst.append(rs.getString("count")).append(" ");
			}
			return "Success " + rst;
		} catch (SQLException e) {
			// TODO 自动生成的 catch 块
			e.printStackTrace();
		}
		return "False";
	}
	
}

class dealRecoms extends Operator {
	dealRecoms(){
		name = "freezing";
        needs = new ArrayList<>();
        needs.add("ISBN");
        level = 2;
        p = new ArrayList<>();
	}
	@Override
	String perform() {
		// TODO 自动生成的方法存根
		Long isbn = Long.parseLong(p.get(0));
		String title = null;
		String author = null;
		Long ISBN = 0L;
		int count = 0;
		if (p.size() < 1) {
			return "Fail: illegal parameters.";
		}
		Connection con = MysqlConnection.getConn();
		try {
			PreparedStatement pps = con.prepareStatement("select * from recommendations where ISBN = ?;");
			pps.setLong(1, isbn);
			ResultSet rs = pps.executeQuery();
			if (rs.next()) {
				title = rs.getString("title");
				author = rs.getString("author");
				ISBN = rs.getLong("ISBN");
				count = rs.getInt("count");
			}
			pps = con.prepareStatement("delete from recommendations where ISBN = ?;");
			pps.setLong(1, isbn);
			pps.executeUpdate();
			Statement stmt = con.createStatement();
			stmt.executeUpdate("insert into books values("+ISBN+",'"+title+"','"+author+"',"+count+","+count+");");
			return "Success";
		} catch (SQLException e) {
			// TODO 自动生成的 catch 块
			e.printStackTrace();
		}
		return "False";
	}
	
}